package com.mall.project.info.controller;


import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mall.common.core.asserts.ApiAssert;
import com.mall.common.core.enums.AuthEnums;
import com.mall.common.core.enums.ErrorCodeEnum;
import com.mall.common.core.model.response.ApiResponses;
import com.mall.common.core.model.supers.SuperController;
import com.mall.common.security.annotation.PreAuth;
import com.mall.common.security.utils.ApiUtils;
import com.mall.common.security.utils.AuthFile;
import com.mall.project.info.model.entity.Photo;
import com.mall.project.info.model.parm.PhotoPARM;
import com.mall.project.info.service.IPhotoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 图片表 前端控制器
 * </p>
 *
 * @author Sam
 * @since 2022-01-04
 */
@Api(tags = {"图片信息"})
@RestController
@RequestMapping("/photo")
public class PhotoRestController extends SuperController {
    @Value("${custom.restPath}")
    private String restPath;

    @Autowired
    private IPhotoService photoService;

    @PreAuth(AuthEnums.OPEN)
    @ResponseBody
    @ApiOperation(value = "上传回调")
    @PostMapping("/callback")
    public String callback(PhotoPARM photoPARM) {
        System.out.println("photoPARM = " + photoPARM);
        Photo photo = photoPARM.convert(Photo.class);
        photo.setStatus("临时");
        photo.setName(photoPARM.getFilename());
        photo.setUrl(photoPARM.getUrl());
        photoService.save(photo);
        return photo.getUrl();
    }

    @PreAuth
    @ResponseBody
    @ApiOperation(value = "获取上传图片token有回调")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "bucket", value = "空间属性（公有、私有）", required = true, paramType = "query"),
    })
    @GetMapping("/token/callback")
    public ApiResponses<String> getTokenCallback(@RequestParam(value = "bucket") String bucket) {
        //服务器回调地址
        String callbackUrl = restPath + "/photo/callback";
        bucket = StringUtils.equals(bucket, "私有") ? "prv" : "pub";
        //前端将callbackBody数据作为picData
        String callbackBody = "filename=$(x:filename)&bucket=$(x:bucket)" +
                "&tableId=$(x:tableId)&tableType=$(x:tableType)&random=" +
                "$(x:random)&mimeType=$(x:mimeType)" +
                "&photoId=$(x:photoId)&userId=$(x:userId)";
        String token = AuthFile.generate(AuthFile.CustomAccessKey, AuthFile.CustomSecretKey, bucket, callbackUrl, callbackBody);
        return success(token);
    }

    @PreAuth
    @ResponseBody
    @ApiOperation(value = "查询图片", response = Photo.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "random", value = "通过图片标识（att）", paramType = "query"),
            @ApiImplicitParam(name = "tableId", value = "外表ID", paramType = "query"),
            @ApiImplicitParam(name = "tableType", value = "外表类型（用户等，待补充）", paramType = "query"),
            @ApiImplicitParam(name = "status", value = "图片状态", paramType = "query"),
            @ApiImplicitParam(name = "pIndex", value = "优先级 true 默认false", dataType = "boolean", paramType = "query"),
    })
    @GetMapping("/list")
    public ApiResponses<List<Photo>> list(@RequestParam(name = "random", required = false) String random,
                                          @RequestParam(name = "tableId", required = false) String tableId,
                                          @RequestParam(name = "tableType", required = false) String tableType,
                                          @RequestParam(name = "status", required = false) String status,
                                          @RequestParam(name = "pIndex", required = false, defaultValue = "false") Boolean pIndex) {
        LambdaQueryWrapper<Photo> wrapper = Wrappers.<Photo>lambdaQuery()
                .eq(StringUtils.isNotEmpty(random), Photo::getRandom, random)
                .eq(StringUtils.isNotEmpty(tableId), Photo::getTableId, tableId)
                .eq(StringUtils.isNotEmpty(tableType), Photo::getTableType, tableType)
                .eq(StringUtils.isNotEmpty(status), Photo::getStatus, status);
        wrapper.last(pIndex, "order by order_num is null, order_num asc");
        List<Photo> photoList = photoService.list(wrapper);
        return success(photoList);
    }

    @PreAuth
    @ResponseBody
    @ApiOperation(value = "保存图片")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "random", value = "随机数", required = true, paramType = "query"),
            @ApiImplicitParam(name = "tableId", value = "外表id", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "tableType", value = "外表类型", paramType = "query"),
    })
    @PostMapping
    public ApiResponses<Void> create(@RequestBody PhotoPARM photoPARM) {
        photoService.savePhoto(photoPARM.getTableId(), photoPARM.getTableType(), photoPARM.getRandom());
        return success();
    }

    @PreAuth
    @ResponseBody
    @ApiOperation(value = "修改图片状态为失效")
    @PutMapping("/failure/{photoId}")
    public ApiResponses<Void> updateFailure(@PathVariable("photoId") Long photoId) {
        Photo photo = new Photo();
        photo.setPhotoId(photoId);
        photo.setStatus("失效");
        ApiAssert.isTrue(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("修改状态失败！"), photoService.updateById(photo));
        return success();
    }

    @PreAuth
    @ResponseBody
    @ApiOperation(value = "恢复修改图片时删除的正常图片")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "tableId", value = "外表ID", paramType = "query"),
            @ApiImplicitParam(name = "tableType", value = "外表类型", required = true, paramType = "query"),
    })
    @PutMapping("/recovery")
    public ApiResponses<Void> recovery(@RequestParam("tableId") String tableId,
                                       @RequestParam("tableType") String tableType) {
        List<Photo> failurePhotoList = photoService.list(Wrappers.<Photo>lambdaQuery()
                .eq(Photo::getTableId, tableId)
                .eq(Photo::getTableType, tableType)
                .eq(Photo::getStatus, "失效")
                .isNull(Photo::getRandom));
        if (CollectionUtils.isNotEmpty(failurePhotoList)) {
            LambdaUpdateWrapper<Photo> wrapper = Wrappers.<Photo>lambdaUpdate()
                    .eq(Photo::getTableId, tableId)
                    .eq(Photo::getTableType, tableType)
                    .isNull(Photo::getRandom)
                    .set(Photo::getStatus, "正常");
            ApiAssert.isTrue(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("恢复失败！"), photoService.update(wrapper));
        }
        return success();
    }

    @PreAuth
    @ResponseBody
    @ApiOperation(value = "删除服务器图片和本地图片")
    @ApiImplicitParam(name = "photoIds", value = "图片ID集合", dataType = "int", required = true, paramType = "query")
    @DeleteMapping
    public ApiResponses<Void> delete(@RequestParam List<Integer> photoIds) {
        if(CollUtil.isEmpty(photoIds)){
            return success();
        }
        List<Photo> photos = photoService.list(new QueryWrapper<Photo>().lambda().in(Photo::getPhotoId, photoIds));
        for (Photo photo : photos) {
            photoService.deletePhoto(photo.getBucket(), photo.getUrl());
            photoService.removeById(photo.getPhotoId());
        }
        return success();
    }

    @PreAuth
    @ResponseBody
    @ApiOperation(value = "根据随机数删除临时图片")
    @ApiImplicitParam(name = "random", value = "随机数", required = true, paramType = "query")
    @DeleteMapping("/temporaryPhoto")
    public ApiResponses<Void> deletePhoto(@RequestParam String random) {
        LambdaQueryWrapper<Photo> queryWrapper = new QueryWrapper<Photo>().lambda().in(Photo::getRandom, random).eq(Photo::getStatus, "临时");
        List<Photo> photos = photoService.list(queryWrapper);
        for (Photo photo : photos) {
            photoService.deletePhoto(photo.getBucket(), photo.getUrl());
            photoService.removeById(photo.getPhotoId());
        }
        return success();
    }

    @PreAuth
    @ResponseBody
    @ApiOperation(value = "生成手机访问的url")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "random", value = "随机数", required = true, paramType = "query"),
            @ApiImplicitParam(name = "tableId", value = "外表ID", paramType = "query"),
            @ApiImplicitParam(name = "tableType", value = "外表类型", required = true, paramType = "query"),
            @ApiImplicitParam(name = "mimeType", value = "文件类型", required = true, paramType = "query"),
            @ApiImplicitParam(name = "bucket", value = "存储空间类型", required = true, paramType = "query"),
    })
    @GetMapping("/getMobUploadUrl")
    public ApiResponses<String> getMobUploadUrl(@RequestParam(value = "random") String random,
                                                @RequestParam(value = "tableId", required = false) String tableId,
                                                @RequestParam(value = "tableType") String tableType,
                                                @RequestParam(value = "mimeType") String mimeType,
                                                @RequestParam(value = "bucket") String bucket) {
        return success(restPath + "/photos/qrUpload?random=" + random + (Objects.nonNull(tableId) ? ("&tableId=" + tableId) : "") +
                "&tableType=" + tableType + "&mimeType=" + mimeType + "&bucket=" + bucket + "&userId=" + ApiUtils.currentUid());
    }

    @ApiOperation(value = "验证qr及co,通过则跳转上传页，不通过则返回error")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "random", value = "随机数", required = true, paramType = "query"),
            @ApiImplicitParam(name = "tableId", value = "外表ID", paramType = "query"),
            @ApiImplicitParam(name = "tableType", required = true, value = "外表类型", paramType = "query"),
            @ApiImplicitParam(name = "mimeType", required = true, value = "文件类型", paramType = "query"),
            @ApiImplicitParam(name = "bucket", required = true, value = "存储空间类型", paramType = "query"),
            @ApiImplicitParam(name = "userId", required = true, value = "上传人ID", paramType = "query"),
    })
    @GetMapping("/qrUpload")
    public String qrUpload(@RequestParam(value = "random") String random,
                           @RequestParam(value = "tableId", required = false) String tableId,
                           @RequestParam(value = "tableType") String tableType,
                           @RequestParam(value = "mimeType") String mimeType,
                           @RequestParam(value = "bucket") String bucket,
                           @RequestParam(value = "userId") Integer userId) {
        try {
            tableType = URLEncoder.encode(tableType, "utf-8");
            mimeType = URLEncoder.encode(mimeType, "utf-8");
            bucket = URLEncoder.encode(bucket, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "redirect:" + restPath + "/photo/mobUpload.html?random=" + random + (StringUtils.isNotEmpty(tableId) ? ("&tableId=" + tableId) : "") +
                "&tableType=" + tableType + "&mimeType=" + mimeType + "&bucket=" + bucket + "&userId=" + userId;
    }
}

